// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   KeyboardDeviceImpl.java

package backstage.runtime.ctrl;

import java.util.*;

import net.java.games.input.Component;
import net.java.games.input.ControllerEnvironment;
import net.java.games.input.Keyboard;
import keel.runtime.KeelRuntime;
import keel.runtime.ctrl.*;
import keel.runtime.event.KeyEvent;

// Referenced classes of package backstage.runtime.ctrl:
//            ControllerConfigSet

public class KeyboardDeviceImpl
    implements KeyboardDevice
{
    static class ControllerRestorerImpl
        implements ControllerRestorer
    {

        public Controller restore()
        {
            KeyboardDevice device = KeelRuntime.getRuntime().getKeyboardDevice();
            if(device == null || !device.checkConversion(descriptor, conversion))
                return null;
            else
                return device.createController(descriptor, conversion);
        }

        ControllerDescriptor descriptor;
        KeyboardDeviceConversion conversion;

        ControllerRestorerImpl(ControllerDescriptor desc, KeyboardDeviceConversion conv)
        {
            descriptor = desc;
            conversion = conv;
        }
    }

    class ControllerImpl extends AbstractController
    {

        KeyboardDeviceConversion getConversion()
        {
            return conversion;
        }

        void setConversion(KeyboardDeviceConversion conv)
        {
            conversion = conv;
        }

        protected boolean updateImpl()
        {
            return true;
        }

        protected boolean[] stateButton(ControllerElement button)
        {
            int code[] = conversion.getKeyCode(button);
            int dimension = button.getNumElements();
            boolean pressed[] = new boolean[dimension];
            for(int j = 0; j < dimension; j++)
                pressed[j] = isPressed(code[j]);

            return pressed;
        }

        protected float[] stateAxis(ControllerElement axis)
        {
            int code[] = conversion.getKeyCode(axis);
            int dimension = axis.getNumElements();
            float point[] = new float[dimension];
            for(int j = 0; j < dimension; j++)
            {
                boolean bottom = isPressed(code[j * 2]);
                boolean top = isPressed(code[j * 2 + 1]);
                if(bottom && top || !bottom && !top)
                    point[j] = 0.0F;
                else
                    point[j] = bottom ? -1F : 1.0F;
            }

            return point;
        }

        protected float[] stateHatswitch(ControllerElement hatswitch)
        {
            int code[] = conversion.getKeyCode(hatswitch);
            int dimension = hatswitch.getNumElements();
            int ways = code.length / dimension;
            float value[] = new float[dimension];
            float valueLast[] = getAxisPoint(hatswitch);
            if(ways == 1)
            {
                for(int j = 0; j < dimension; j++)
                {
                    value[j] = valueLast[j];
                    if(isPressed(code[j]))
                    {
                        if(!onewayHatswitchPushed)
                        {
                            value[j] = value[j] + 1.570796F;
                            if((double)value[j] >= 6.2831853071795862D)
                                value[j] = 0.0F;
                            onewayHatswitchPushed = true;
                        }
                    } else
                    {
                        onewayHatswitchPushed = false;
                    }
                }

            } else
            {
                for(int j = 0; j < dimension; j++)
                {
                    value[j] = 0.0F;
                    for(int k = 0; k < ways; k++)
                    {
                        if(!isPressed(code[j * ways + k]))
                            continue;
                        value[j] = ((float)(k * 2) * 3.141593F) / (float)ways;
                        break;
                    }

                }

            }
            return value;
        }

        public void dispose()
        {
            deleteController(this);
        }

        public boolean equals(Object o)
        {
            if(!super.equals(o))
                return false;
            return o instanceof ControllerImpl;
        }

        public ControllerRestorer getRestorer()
        {
            return new ControllerRestorerImpl(descriptor, conversion);
        }

        public Object getSource()
        {
            return KeyboardDeviceImpl.this;
        }

        KeyboardDeviceConversion conversion;
        boolean onewayHatswitchPushed;
        int onewayHatswitchValue;

        public ControllerImpl(ControllerDescriptor descriptor)
        {
            super(descriptor);
            onewayHatswitchValue = 0;
            onewayHatswitchPushed = false;
        }
    }


    public KeyboardDeviceImpl()
    {
        controllerList = Collections.synchronizedList(new ArrayList());
        ArrayList keyList=new ArrayList();
        
        net.java.games.input.Controller ctrls[]=ControllerEnvironment.getDefaultEnvironment().getControllers();
    	for(int i=0;i<ctrls.length;++i)
    		if(ctrls[i].getType()==net.java.games.input.Controller.Type.KEYBOARD)
    			keyList.add((Keyboard)ctrls[i]);
    	
    	keyconts=(Keyboard[])keyList.toArray(new Keyboard[0]);
    }
    
    private boolean isPressedAlone(Keyboard keycont,int keyCode)
    {
    	keycont.poll();
    	switch(keyCode)
    	{
    	case KeyEvent.VK_ALT:
    		return keycont.isKeyDown(Component.Identifier.Key.LALT) || keycont.isKeyDown(Component.Identifier.Key.RALT);
    	case KeyEvent.VK_CONTROL:
    		return keycont.isKeyDown(Component.Identifier.Key.LCONTROL) || keycont.isKeyDown(Component.Identifier.Key.RCONTROL);
    	case KeyEvent.VK_SHIFT:
    		return keycont.isKeyDown(Component.Identifier.Key.LSHIFT) || keycont.isKeyDown(Component.Identifier.Key.RSHIFT);
    	case KeyEvent.VK_COMMA:
    		return keycont.isKeyDown(Component.Identifier.Key.COMMA) || keycont.isKeyDown(Component.Identifier.Key.NUMPADCOMMA);
    	case KeyEvent.VK_ENTER:
    		return keycont.isKeyDown(Component.Identifier.Key.RETURN) || keycont.isKeyDown(Component.Identifier.Key.NUMPADENTER);
    	case KeyEvent.VK_EQUALS:
    		return keycont.isKeyDown(Component.Identifier.Key.EQUALS) || keycont.isKeyDown(Component.Identifier.Key.NUMPADEQUAL);
    	case KeyEvent.VK_META:
    		return keycont.isKeyDown(Component.Identifier.Key.LWIN) || keycont.isKeyDown(Component.Identifier.Key.RWIN);
    	
    	default:
    		Component.Identifier.Key t=getKey(keyCode);
    		if(t==Component.Identifier.Key.UNKNOWN)
    			return false;
    		return keycont.isKeyDown(t);
    	}
    }

    public boolean isPressed(int keyCode)
    {
    	for(int i=0;i<keyconts.length;++i)
    		if(isPressedAlone(keyconts[i], keyCode))
    			return true;
    	
    	return false;
    }

    public int waitForStroke(long timeout)
        throws InterruptedException
    {
        return 0;
    }

    public synchronized Controller createController(ControllerDescriptor descriptor, KeyboardDeviceConversion conversion)
    {
        if(descriptor == null)
        {
            throw new NullPointerException("descriptor is null");
        } else
        {
            ControllerImpl ct = new ControllerImpl(descriptor);
            controllerList.add(ct);
            setConversion(ct, conversion);
            return ct;
        }
    }

    public synchronized void updateConfig()
    {
        Controller keyctrls[] = getControllers();
        for(int l = 0; l < keyctrls.length; l++)
        {
            ControllerImpl ctrl = (ControllerImpl)keyctrls[l];
            ctrl.setConversion(ControllerConfigSet.getConfigSet().getKeyboardDeviceConversion(l, ctrl.getDescriptor()));
        }

    }

    public synchronized void deleteController(Controller controller)
    {
        controllerList.remove(controller);
    }

    public synchronized Controller[] getControllers()
    {
        return (Controller[])controllerList.toArray(new Controller[0]);
    }

    public synchronized void setConversion(Controller ct, KeyboardDeviceConversion conv)
    {
        if(!controllerList.contains(ct))
            throw new IllegalArgumentException("couldn't find controller : " + ct);
        if(conv == null)
            throw new NullPointerException("conv is null");
        KeyboardDeviceConversion conversion = (KeyboardDeviceConversion)conv.clone();
        if(!checkConversion(ct.getDescriptor(), conversion))
            throw new IllegalArgumentException("illegal conversion");
        ((ControllerImpl)ct).setConversion(conversion);
        String idStr = ct.getName();
        if(idStr != null)
        {
            idStr = idStr.substring(idStr.lastIndexOf(' ') + 1);
            try
            {
                int id = Integer.parseInt(idStr);
                ControllerConfigSet.getConfigSet().putKeyboardDeviceConversion(id, ct.getDescriptor(), conv);
            }
            catch(NumberFormatException e) { }
        }
    }

    public synchronized KeyboardDeviceConversion getConversion(Controller ct)
    {
        if(!controllerList.contains(ct))
        {
            throw new IllegalArgumentException("couldn't find controller : " + ct);
        } else
        {
            KeyboardDeviceConversion conv = ((ControllerImpl)ct).getConversion();
            return conv;
        }
    }

    public boolean checkConversion(ControllerDescriptor descriptor, KeyboardDeviceConversion conversion)
    {
        for(Iterator i = descriptor.getButtons().iterator(); i.hasNext();)
        {
            ControllerElement button = (ControllerElement)i.next();
            int code[] = conversion.getKeyCode(button);
            if(code == null)
                return false;
        }

        for(Iterator i = descriptor.getAxes().iterator(); i.hasNext();)
        {
            ControllerElement axis = (ControllerElement)i.next();
            int code[] = conversion.getKeyCode(axis);
            if(code == null)
                return false;
        }

        for(Iterator i = descriptor.getHatswitches().iterator(); i.hasNext();)
        {
            ControllerElement hatswith = (ControllerElement)i.next();
            int code[] = conversion.getKeyCode(hatswith);
            if(code == null)
                return false;
        }

        return true;
    }

    Component.Identifier.Key getKey(int key)
    {
    	switch(key)
    	{
    	case KeyEvent.VK_0:
    		return Component.Identifier.Key._0;
    	case KeyEvent.VK_1:
    		return Component.Identifier.Key._1;
    	case KeyEvent.VK_2:
    		return Component.Identifier.Key._2;
    	case KeyEvent.VK_3:
    		return Component.Identifier.Key._3;
    	case KeyEvent.VK_4:
    		return Component.Identifier.Key._4;
    	case KeyEvent.VK_5:
    		return Component.Identifier.Key._5;
    	case KeyEvent.VK_6:
    		return Component.Identifier.Key._6;
    	case KeyEvent.VK_7:
    		return Component.Identifier.Key._7;
    	case KeyEvent.VK_8:
    		return Component.Identifier.Key._8;
    	case KeyEvent.VK_9:
    		return Component.Identifier.Key._9;
    	case KeyEvent.VK_A:
    		return Component.Identifier.Key.A;
    	case KeyEvent.VK_ADD:
    		return Component.Identifier.Key.ADD;
    	case KeyEvent.VK_QUOTE:
    		return Component.Identifier.Key.APOSTROPHE;
    	case KeyEvent.VK_AT:
    		return Component.Identifier.Key.AT;
    	case KeyEvent.VK_B:
    		return Component.Identifier.Key.B;
    	case KeyEvent.VK_BACK_SPACE:
    		return Component.Identifier.Key.BACK;
    	case KeyEvent.VK_BACK_SLASH:
    		return Component.Identifier.Key.BACKSLASH;
    	case KeyEvent.VK_C:
    		return Component.Identifier.Key.C;
    	case KeyEvent.VK_CAPS_LOCK:
    		return Component.Identifier.Key.CAPITAL;
    	case KeyEvent.VK_CIRCUMFLEX:
    		return Component.Identifier.Key.CIRCUMFLEX;
    	case KeyEvent.VK_COLON:
    		return Component.Identifier.Key.COLON;
    	case KeyEvent.VK_CONVERT:
    		return Component.Identifier.Key.CONVERT;
    	case KeyEvent.VK_D:
    		return Component.Identifier.Key.D;
    	case KeyEvent.VK_DECIMAL:
    		return Component.Identifier.Key.DECIMAL;
    	case KeyEvent.VK_DELETE:
    		return Component.Identifier.Key.DELETE;
    	case KeyEvent.VK_DIVIDE:
    		return Component.Identifier.Key.DIVIDE;
    	case KeyEvent.VK_DOWN:
    		return Component.Identifier.Key.DOWN;
    	case KeyEvent.VK_E:
    		return Component.Identifier.Key.E;
    	case KeyEvent.VK_END:
    		return Component.Identifier.Key.END;
    	case KeyEvent.VK_ESCAPE:
    		return Component.Identifier.Key.ESCAPE;
    	case KeyEvent.VK_F:
    		return Component.Identifier.Key.F;
    	case KeyEvent.VK_F1:
    		return Component.Identifier.Key.F1;
    	case KeyEvent.VK_F2:
    		return Component.Identifier.Key.F2;
    	case KeyEvent.VK_F3:
    		return Component.Identifier.Key.F3;
    	case KeyEvent.VK_F4:
    		return Component.Identifier.Key.F4;
    	case KeyEvent.VK_F5:
    		return Component.Identifier.Key.F5;
    	case KeyEvent.VK_F6:
    		return Component.Identifier.Key.F6;
    	case KeyEvent.VK_F7:
    		return Component.Identifier.Key.F7;
    	case KeyEvent.VK_F8:
    		return Component.Identifier.Key.F8;
    	case KeyEvent.VK_F9:
    		return Component.Identifier.Key.F9;
    	case KeyEvent.VK_F10:
    		return Component.Identifier.Key.F10;
    	case KeyEvent.VK_F11:
    		return Component.Identifier.Key.F11;
    	case KeyEvent.VK_F12:
    		return Component.Identifier.Key.F12;
    	case KeyEvent.VK_F13:
    		return Component.Identifier.Key.F13;
    	case KeyEvent.VK_F14:
    		return Component.Identifier.Key.F14;
    	case KeyEvent.VK_F15:
    		return Component.Identifier.Key.F15;
    	case KeyEvent.VK_G:
    		return Component.Identifier.Key.G;
    	case KeyEvent.VK_BACK_QUOTE:
    		return Component.Identifier.Key.GRAVE;
    	case KeyEvent.VK_H:
    		return Component.Identifier.Key.H;
    	case KeyEvent.VK_HOME:
    		return Component.Identifier.Key.HOME;
    	case KeyEvent.VK_I:
    		return Component.Identifier.Key.I;
    	case KeyEvent.VK_INSERT:
    		return Component.Identifier.Key.INSERT;
    	case KeyEvent.VK_J:
    		return Component.Identifier.Key.J;
    	case KeyEvent.VK_K:
    		return Component.Identifier.Key.K;
    	case KeyEvent.VK_KANA:
    		return Component.Identifier.Key.KANA;
    	case KeyEvent.VK_KANJI:
    		return Component.Identifier.Key.KANJI;
    	case KeyEvent.VK_L:
    		return Component.Identifier.Key.L;
    	case KeyEvent.VK_LEFT:
    		return Component.Identifier.Key.LEFT;
    	case KeyEvent.VK_M:
    		return Component.Identifier.Key.M;
    	case KeyEvent.VK_MINUS:
    		return Component.Identifier.Key.MINUS;
    	case KeyEvent.VK_MULTIPLY:
    		return Component.Identifier.Key.MULTIPLY;
    	case KeyEvent.VK_N:
    		return Component.Identifier.Key.N;
    	case KeyEvent.VK_NONCONVERT:
    		return Component.Identifier.Key.NOCONVERT;
    	case KeyEvent.VK_NUM_LOCK:
    		return Component.Identifier.Key.NUMLOCK;
    	case KeyEvent.VK_NUMPAD0:
    		return Component.Identifier.Key.NUMPAD0;
    	case KeyEvent.VK_NUMPAD1:
    		return Component.Identifier.Key.NUMPAD1;
    	case KeyEvent.VK_NUMPAD2:
    		return Component.Identifier.Key.NUMPAD2;
    	case KeyEvent.VK_NUMPAD3:
    		return Component.Identifier.Key.NUMPAD3;
    	case KeyEvent.VK_NUMPAD4:
    		return Component.Identifier.Key.NUMPAD4;
    	case KeyEvent.VK_NUMPAD5:
    		return Component.Identifier.Key.NUMPAD5;
    	case KeyEvent.VK_NUMPAD6:
    		return Component.Identifier.Key.NUMPAD6;
    	case KeyEvent.VK_NUMPAD7:
    		return Component.Identifier.Key.NUMPAD7;
    	case KeyEvent.VK_NUMPAD8:
    		return Component.Identifier.Key.NUMPAD8;
    	case KeyEvent.VK_NUMPAD9:
    		return Component.Identifier.Key.NUMPAD9;
    	case KeyEvent.VK_O:
    		return Component.Identifier.Key.O;
    	case KeyEvent.VK_P:
    		return Component.Identifier.Key.P;
    	case KeyEvent.VK_PAGE_DOWN:
    		return Component.Identifier.Key.PAGEDOWN;
    	case KeyEvent.VK_PAGE_UP:
    		return Component.Identifier.Key.PAGEUP;
    	case KeyEvent.VK_PAUSE:
    		return Component.Identifier.Key.PAUSE;
    	case KeyEvent.VK_PERIOD:
    		return Component.Identifier.Key.PERIOD;
    	case KeyEvent.VK_Q:
    		return Component.Identifier.Key.Q;
    	case KeyEvent.VK_R:
    		return Component.Identifier.Key.R;
    	case KeyEvent.VK_RIGHT:
    		return Component.Identifier.Key.RIGHT;
    	case KeyEvent.VK_S:
    		return Component.Identifier.Key.S;
    	case KeyEvent.VK_SCROLL_LOCK:
    		return Component.Identifier.Key.SCROLL;
    	case KeyEvent.VK_SEMICOLON:
    		return Component.Identifier.Key.SEMICOLON;
    	case KeyEvent.VK_SLASH:
    		return Component.Identifier.Key.SLASH;
    	case KeyEvent.VK_SPACE:
    		return Component.Identifier.Key.SPACE;
    	case KeyEvent.VK_STOP:
    		return Component.Identifier.Key.STOP;
    	case KeyEvent.VK_SUBTRACT:
    		return Component.Identifier.Key.SUBTRACT;
    	case KeyEvent.VK_T:
    		return Component.Identifier.Key.T;
    	case KeyEvent.VK_TAB:
    		return Component.Identifier.Key.TAB;
    	case KeyEvent.VK_U:
    		return Component.Identifier.Key.U;
    	case KeyEvent.VK_UNDERSCORE:
    		return Component.Identifier.Key.UNDERLINE;
    	case KeyEvent.VK_UP:
    		return Component.Identifier.Key.UP;
    	case KeyEvent.VK_V:
    		return Component.Identifier.Key.V;
    	case KeyEvent.VK_W:
    		return Component.Identifier.Key.W;
    	case KeyEvent.VK_X:
    		return Component.Identifier.Key.X;
    	case KeyEvent.VK_Y:
    		return Component.Identifier.Key.Y;
    	case KeyEvent.VK_Z:
    		return Component.Identifier.Key.Z;
    	case KeyEvent.VK_OPEN_BRACKET:
    		return Component.Identifier.Key.LBRACKET;
    	case KeyEvent.VK_CLOSE_BRACKET:
    		return Component.Identifier.Key.RBRACKET;
        		
    	default:
    		return Component.Identifier.Key.UNKNOWN;
    	}
    }

    Keyboard keyconts[];
    List controllerList;
}
